package com.katze.boot.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.katze.boot.plugins.redis.service.CacheService;
import com.katze.boot.system.dao.RoleMapper;
import com.katze.boot.system.domain.Role;
import com.katze.boot.system.service.RoleMenuService;
import com.katze.boot.system.service.RoleService;
import com.katze.boot.system.service.UserRoleService;
import com.katze.common.Pagination;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Service("roleService")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
    @Resource
    private UserRoleService userRoleService;
    @Resource
    private RoleMenuService roleMenuService;
    @Resource
    private CacheService cacheService;

    @Override
    public Object findRoles(Pagination pagination, Role role) {
        if (pagination.isEnabled()) {
            return this.baseMapper.findRoles(pagination.toPage(), role);
        } else {
            LambdaQueryWrapper<Role> queryWrapper = Wrappers.lambdaQuery(Role.class)
                    .like(StringUtils.isNotBlank(role.getRoleName()), Role::getRoleName, role.getRoleName())
                    .like(StringUtils.isNotBlank(role.getAlias()), Role::getAlias, role.getAlias());
            return this.baseMapper.selectList(queryWrapper);
        }
    }

    @Override
    public boolean exists(String roleName) {
        return super.exists(new LambdaQueryWrapper<Role>().eq(Role::getRoleName, roleName));
    }

    @Override
    public void createRole(Role role) {
        role.setCreateTime(new Date());
        super.save(role);
        // 保存角色和菜单关系
        this.roleMenuService.save(role);
    }

    @Override
    public void updateRole(Role role) {
        role.setModifyTime(new Date());
        this.baseMapper.updateById(role);
        // 重新保存角色和菜单关联关系，并清除用户权限缓存
        List<String> users = this.roleMenuService.resetRoleMenus(role).apply(userRoleService::findUsernameByRoleId);
        users.forEach(cacheService::clearUserCache);
    }

    @Override
    public void deleteRoles(Object[] roleIds) {
        // 查找这些角色关联了那些用户
        List<String> users = this.userRoleService.findUsernameByRoleId(roleIds);
        // 删除角色
        this.baseMapper.delete(Wrappers.lambdaQuery(Role.class).in(Role::getRoleId, roleIds));
        // 删除角色，菜单，用户关联关系
        this.roleMenuService.deleteRoleMenusByRoleId(roleIds);
        this.userRoleService.deleteUserRolesByRoleId(roleIds);
        // 重新将这些用户的角色和权限缓存到 Redis中
        users.forEach(cacheService::clearUserCache);
    }
}